package com.tqyan.service.service.impl;

import com.tqyan.dal.mapper.DataShadowMapper;
import com.tqyan.model.controller.request.DataShadowRequest;
import com.tqyan.model.controller.request.OpenAIChatRequest;
import com.tqyan.model.dto.DataShadowDTO;
import com.tqyan.model.exp.DefaultException;
import com.tqyan.service.service.DataShadowService;
import com.tqyan.service.transfer.WordService;
import com.tqyan.util.SnowflakeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 问题先验服务
 * <p> <功能详细描述> </p>
 *
 * @author 陈晨
 * @version 1.0
 * @date 2023/4/18
 */
@Service
@Slf4j
public class DataShadowServiceImpl implements DataShadowService {

    @Autowired
    private DataShadowMapper dataShadowMapper;

    @Autowired
    private WordService wordService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void set(DataShadowRequest request) {
        if (null == request) {
            return;
        }
        if (StringUtils.isBlank(request.getName())) {
            throw new DefaultException("角色名称不可为空");
        }
//        if (StringUtils.isBlank(request.getDescription())
//                || request.getDescription().length() < 30) {
//            throw new DefaultException("角色描述太简单可能会不太清晰哦, 至少30字符");
//        }
//        if (request.getDescription().length() > 300) {
//            throw new DefaultException("角色描述最多300字符哦");
//        }
        // 数字缩影入库
        DataShadowDTO dataShadow = dataShadowMapper.queryByName(request.getName());
        if (null == dataShadow) {
            this.save(request);
        } else {
            this.update(request, dataShadow);
        }
    }

    /**
     * @description 新增
     * <p> <功能详细描述> </p>
     *
     * @author 陈晨
     * @date 2023/4/20 17:28
     */
    private void save(DataShadowRequest request) {
        // 数字缩影
        DataShadowDTO dataShadow = new DataShadowDTO();
        dataShadow.setId(SnowflakeUtils.nextId());
        dataShadow.setName(request.getName());
        dataShadow.setDescription(request.getDescription());
        dataShadow.setKeywords(request.getName() + "," + wordService.extract(request.getDescription()));
        if ("我们".equals(dataShadow.getName())) {
            dataShadow.setKeywords("我们,葡萄,葡萄酒,红酒,酒,俱乐部,得到,上海,14期,发酵,香气,温度");
        }
        boolean result = dataShadowMapper.save(List.of(dataShadow)) > 0;
        log.info("[数字缩影] request={}, dataShadow={}, 数字缩影入库: {}", request, dataShadow, result);
        if (!result) {
            throw new DefaultException("数字缩影添加失败");
        }
        // 提取关键词
        this.extractKeyword(dataShadow);
        log.info("[数字缩影] dataShadow={}, 提取关键词", dataShadow);
    }

    /**
     * @description 更新
     * <p> <功能详细描述> </p>
     *
     * @author 陈晨
     * @date 2023/4/20 17:28
     */
    private void update(DataShadowRequest request, DataShadowDTO dataShadow) {
        // 数字缩影
        DataShadowDTO updateDataShadow = new DataShadowDTO();
        updateDataShadow.setId(dataShadow.getId());
        updateDataShadow.setDescription(request.getDescription());
        updateDataShadow.setKeywords(dataShadow.getName() + "," + wordService.extract(request.getDescription()));
        if ("我们".equals(dataShadow.getName())) {
            updateDataShadow.setKeywords("我们,葡萄,葡萄酒,红酒,酒,俱乐部,得到,上海,14期,发酵,香气,温度");
        }
        boolean result = dataShadowMapper.update(updateDataShadow) > 0;
        log.info("[数字缩影] request={}, 数字缩影更新: {}", request, result);
        if (!this.isUpdateKeyword(request.getDescription(), dataShadow.getDescription())) {
            return;
        }
        // 删除当前关键词-数字缩影关系
        for (String keyword : dataShadow.getKeywords().split(",")) {
            result = dataShadowMapper.deleteMapping(keyword, dataShadow.getId()) > 0;
            log.info("[数字缩影] dataShadow={}, keyword={}, 删除当前关键词-数字缩影认知: {}"
                    , dataShadow, keyword, result);
        }
        // 更新关键词
        updateDataShadow.setName(dataShadow.getName());
        this.extractKeyword(updateDataShadow);
        log.info("[数字缩影] dataShadow={}, updateDataShadow={}, 更新关键词", dataShadow, updateDataShadow);
    }

    /**
     * @description 判断是否更新关键词
     * <p> <功能详细描述> </p>
     *
     * @author 陈晨
     * @date 2023/4/20 18:08
     */
    private boolean isUpdateKeyword(String requestContent, String oriContent) {
        if (StringUtils.isBlank(requestContent)) {
            return false;
        }
        if (StringUtils.isBlank(oriContent)) {
            return true;
        }
        // 相似率低于67%, 则更新关键词
        double rate = wordService.calculateStringSimilarity(requestContent, oriContent);
        log.info("[数字缩影] requestContent={}, oriContent={}, 相似率: {}", requestContent, oriContent, rate);
        return rate < 0.67;
    }

    /**
     * @description 提取数字缩影关键字
     * <p> <功能详细描述> </p>
     *
     * @author 陈晨
     * @date 2023/4/20 14:21
     */
    private void extractKeyword(DataShadowDTO dataShadow) {
        for (String keyword : dataShadow.getKeywords().split(",")) {
            Map<String, Object> mapping = new HashMap<>();
            mapping.put("id", SnowflakeUtils.nextId());
            mapping.put("keyword", keyword);
            mapping.put("dataShadowId", dataShadow.getId());
            boolean result = dataShadowMapper.saveMapping(mapping) > 0;
            log.info("[数字缩影] mapping={}, 关键词-数字缩影关系入库: {}", mapping, result);
            if (!result) {
                throw new DefaultException("关键词-数字缩影关系入库失败");
            }
        }
    }

    @Override
    public String queryDescription(String name) {
        if (StringUtils.isBlank(name)) {
            return "";
        }
        DataShadowDTO dataShadow = dataShadowMapper.queryByName(name);
        if (null == dataShadow) {
            return "";
        }
        return dataShadow.getDescription();
    }

    @Override
    public List<DataShadowDTO> queryByKeyword(List<String> keywordList) {
        // 查询关键词对应的数字缩影ID
        Set<Long> idSet = new HashSet<>();
        for (String keyword : keywordList) {
            if (StringUtils.isBlank(keyword)) {
                continue;
            }
            idSet.addAll(dataShadowMapper.queryByKeyword(keyword));
        }
        if (CollectionUtils.isEmpty(idSet)) {
            return Collections.emptyList();
        }
        List<DataShadowDTO> resultList = new ArrayList<>();
        for (Long id : idSet) {
            DataShadowDTO dataShadow = dataShadowMapper.queryById(id);
            if (null == dataShadow) {
                continue;
            }
            resultList.add(dataShadow);
        }
        return resultList;
    }

    @Override
    public boolean appendDataShadow(List<String> questionKeywordList, OpenAIChatRequest chatRequest) {
        if (CollectionUtils.isEmpty(questionKeywordList) || null == chatRequest) {
            return false;
        }
        // 关键词查询
        List<DataShadowDTO> dataShadowList = this.queryByKeyword(questionKeywordList);
        log.info("[数字缩影] questionKeywordList={}, dataShadowList={}, 关键词查询"
                , questionKeywordList, dataShadowList.stream().map(DataShadowDTO::getName).collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(dataShadowList)) {
            return false;
        }
        // 计算编辑距离, 匹配认知
        String questionKeywords = StringUtils.join(questionKeywordList, ",");
        List<DataShadowDTO> useList = new ArrayList<>();
//        double useRate = 0.33;
        double useRate = 0.17;
        for (DataShadowDTO dataShadow : dataShadowList) {
            if (null == dataShadow) {
                continue;
            }
            // 完全包含, 则直接匹配
            if (dataShadow.getKeywords().contains(questionKeywords)) {
                useList.add(dataShadow);
                continue;
            }
            // 计算编辑距离
            double rate = wordService.calculateStringSimilarity(questionKeywords, dataShadow.getKeywords());
            log.info("[数字缩影] questionKeywords={}, dataShadow.getKeywords={}, chatRequest={}, useRate={}, rate={}, 计算编辑距离, 匹配数字缩影"
                    , questionKeywords, dataShadow.getKeywords(), chatRequest, useRate, rate);
            if (rate > useRate) {
                useList.add(dataShadow);
            }
        }
        log.info("[数字缩影] questionKeywords={}, chatRequest={}, useRate={}, useSize={}, 计算编辑距离, 匹配数字缩影"
                , questionKeywords, chatRequest, useRate, useList.size());
        if (CollectionUtils.isEmpty(useList)) {
            return false;
        }
        /**
         * 匹配数字缩影认知
         * 目前：随机
         * 后期：权重
         * 	    用户粉丝数
         * 	    认知被赞数
         * 	    新认知优先权
         */
        int rnd = (int) (Math.random() * useList.size());
        DataShadowDTO use = useList.get(rnd);
        // 提问追加数字缩影
        String content = String.format("现在我希望你是“%s，%s”\n\nHey AI Assistant，作为“%s“，你觉得："
                , use.getName(), use.getDescription(), use.getName());
        chatRequest.leftPad(content);
//        chatRequest.rightPad("考虑清楚再回答。");
//        chatRequest.rightPad("一步一步的回答。");
        log.info("[数字缩影] questionKeywords={}, chatRequest={}, useRate={}, useSize={}, rnd={}, 提问追加数字缩影"
                , questionKeywords, chatRequest, useRate, useList.size(), rnd);
        return true;
    }

    public static void main(String[] args) {
        WordService wordService = new WordService();
        String name = "李白";
        String keywords = name + "," + "》《,”。,青莲居士,将进酒,诗仙,西成纪,当涂县,早发,酒中,”，";
        String question = "李白";
        double useRate = 0.33;
        useRate = wordService.calculateStringSimilarity(question, keywords);

        if (keywords.contains(question)) {
            System.out.println("全匹配");
        }
        System.out.println(question);
        System.out.println(keywords);
        System.out.println(useRate);
    }

}


